import os
import time
import json
import base64
import requests
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from loguru import logger

# 配置日志 - 与服务器使用同一个日志文件
log_file = "file_transfer.log"
logger.add(
    log_file,
    format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}",
    level="INFO",
    rotation="10 MB",  # 日志文件达到10MB时自动轮转
    retention="30 days",  # 保留30天的日志
    encoding="utf-8"
)

# 配置参数
WATCH_DIR = r"D:\Cloud_Edge_End\H960\update_h960-App_v1.4.6.3_b20250224\Data"
SERVER_URL = "http://192.168.1.109:8000"

# 确保监控目录存在
os.makedirs(WATCH_DIR, exist_ok=True)
logger.info(f"监控目录：{WATCH_DIR}，服务器地址：{SERVER_URL}")


def is_file_complete(file_path, check_interval=2, check_times=3):
    """检查文件是否上传完成"""
    if not os.path.exists(file_path):
        logger.debug(f"文件不存在：{file_path}")
        return False

    # 尝试以独占方式打开文件
    try:
        with open(file_path, 'rb') as f:
            pass
    except PermissionError:
        logger.debug(f"文件被占用：{file_path}")
        return False

    # 检查文件大小是否稳定
    prev_size = os.path.getsize(file_path)
    for i in range(check_times):
        time.sleep(check_interval)
        current_size = os.path.getsize(file_path)
        if current_size != prev_size:
            logger.debug(f"文件大小变化：{file_path}，前：{prev_size}，后：{current_size}")
            return False
        prev_size = current_size

    logger.debug(f"文件已完成写入：{file_path}，大小：{prev_size} 字节")
    return True


def send_file_via_http(file_path, server_url):
    """通过HTTP发送文件"""
    try:
        filename = os.path.basename(file_path)
        file_size = os.path.getsize(file_path)
        logger.info(f"准备发送文件：{filename}，大小：{file_size} 字节")

        # 读取文件内容
        with open(file_path, 'rb') as f:
            file_data = f.read()

        # 准备请求数据
        payload = {
            "metadata": {
                "filename": filename,
                "file_size": file_size
            },
            "file_content": base64.b64encode(file_data).decode('utf-8')
        }

        # 发送请求
        logger.debug(f"向服务器 {server_url} 发送文件 {filename}")
        response = requests.post(server_url, json=payload)

        # 记录响应信息
        logger.info(f"HTTP响应状态码：{response.status_code}")
        if response.text:
            try:
                response_data = response.json()
                logger.debug(f"响应内容：{json.dumps(response_data, indent=2)}")
            except:
                logger.debug(f"响应文本：{response.text[:500]}")  # 只打印前500字符

        # 处理响应
        if response.status_code == 200:
            result = response.json()
            if result.get('status') == 'success':
                success_msg = f"文件 {filename} 发送成功！服务器确认接收，大小：{result.get('size', '未知')} 字节"
                logger.info(success_msg)
                return True
            else:
                error_msg = f"服务器处理失败：{result.get('message', '未知错误')}"
                logger.error(error_msg)
        else:
            error_msg = f"HTTP错误：{response.status_code} - {response.reason}"
            logger.error(error_msg)

        return False

    except Exception as e:
        error_msg = f"发送文件 {filename} 时发生错误：{str(e)}"
        logger.error(error_msg)
        return False


class FileMonitorHandler(FileSystemEventHandler):
    """文件系统事件处理器"""

    def __init__(self):
        self.processing_files = set()
        logger.info("文件监控处理器初始化完成")

    def on_created(self, event):
        if not event.is_directory:
            file_path = event.src_path
            logger.info(f"检测到新文件：{file_path}")

            if file_path in self.processing_files:
                logger.debug(f"文件 {file_path} 正在处理中，跳过重复处理")
                return

            self.processing_files.add(file_path)
            logger.debug(f"开始处理文件：{file_path}")

            # 等待文件完成写入
            while not is_file_complete(file_path):
                filename = os.path.basename(file_path)
                logger.info(f"文件 {filename} 尚未上传完成，等待中...")
                time.sleep(3)

            filename = os.path.basename(file_path)
            file_size = os.path.getsize(file_path)
            logger.info(f"文件 {filename} 上传完成，准备发送，大小：{file_size} 字节")

            # 发送文件到服务器
            if send_file_via_http(file_path, SERVER_URL):
                try:
                    os.remove(file_path)
                    logger.info(f"文件 {filename} 已从监控文件夹中删除")
                except Exception as e:
                    error_msg = f"删除文件 {filename} 时发生错误：{e}"
                    logger.error(error_msg)
            else:
                logger.warning(f"文件 {filename} 发送失败，保留在文件夹中")

            self.processing_files.remove(file_path)
            logger.debug(f"文件 {file_path} 处理完毕")


def start_monitoring(watch_dir):
    """开始监控文件夹"""
    event_handler = FileMonitorHandler()
    observer = Observer()
    observer.schedule(event_handler, watch_dir, recursive=False)
    observer.start()
    logger.info(f"开始监控文件夹：{watch_dir}")
    print(f"开始监控文件夹：{watch_dir}")
    print("按Ctrl+C停止程序")

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
        logger.info("用户中断，监控已停止")
        print("\n监控已停止")
    observer.join()
    logger.info("监控程序已完全退出")


if __name__ == "__main__":
    start_monitoring(WATCH_DIR)
